﻿using System;
using System.Collections;
using System.Data;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using CObject;
using Objects.CMT;
using Objects.Security;

public partial class ObjectManagement :   Objects.cSecurePage
{
    #region Properties

    /// <summary>
    /// Gets or sets the Object ID
    /// </summary>
    public int ObjectID
    {
        get
        {
            if (ViewState["ObjectID"] == null)
                return 0;
            else
                return int.Parse(ViewState["ObjectID"].ToString());

        }
        set { ViewState["ObjectID"] = value; }
    }

    #endregion

    #region Events

    /// <summary>
    /// Page load event
    /// </summary>
    /// <param name="sender">The sending object</param>
    /// <param name="e">The page load event arguments.</param>
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!this.Page.IsPostBack)
        {
            this.BindObjects();
        }
    }

    /// <summary>
    /// Event for saving new Object details
    /// </summary>
    /// <param name="sender">The sending object</param>
    /// <param name="e">The event arguments.</param>
    protected void btnSave_Click(object sender, EventArgs e)
    {
        if (Page.IsValid)
        {
            SecurityObject securityObject = new SecurityObject();
            if (this.ObjectID > 0)
                securityObject.ObjectID = this.ObjectID;           
            securityObject.Sort = string.IsNullOrEmpty(txtSortOrder.Text) ? 0 : Convert.ToInt32(txtSortOrder.Text);
            securityObject.Target = txtTarget.Text;
            securityObject.Href = txtHref.Text;
            securityObject.Type = txtType.Text;
            securityObject.Description = txtDescription.Text.Trim();
            securityObject.Name = txtName.Text.Trim();
            securityObject.Parent = int.Parse(ddlParentMenu.SelectedValue);          
            ArrayList assignedRoles = new ArrayList();
            foreach (ListItem lstRole in lstAssignedRoles.Items)
            {
                assignedRoles.Add(int.Parse(lstRole.Value));
            }

            securityObject.RoleIDs = assignedRoles;
            if (this.SaveObject(securityObject))
            {
                this.BindObjects();
                ScriptManager.RegisterStartupScript(this, this.GetType(), "hideaddnew", "HideAddNew()", true);

                // Clear the values
                this.ClearControls();
            }
            else
            {
                lblErrorAddNew.Text = "Object Name is not unique";
            }
        }
    }

    /// <summary>
    /// Adding roles to assign listbox
    /// </summary>
    /// <param name="sender">The sending object</param>
    /// <param name="e">Event arguments</param>
    protected void btnAddRoles_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < lstRoles.Items.Count; i++)
        {
            if (lstRoles.Items[i].Selected)
            {
                lstAssignedRoles.Items.Add(lstRoles.Items[i]);
                lstRoles.Items.RemoveAt(i);
            }
        }
    }

    /// <summary>
    /// Removing assigned roles to the user
    /// </summary>
    /// <param name="sender">The sending object</param>
    /// <param name="e">The event arguments</param>
    protected void btnRemoveRoles_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < lstAssignedRoles.Items.Count; i++)
        {
            if (lstAssignedRoles.Items[i].Selected)
            {
                lstRoles.Items.Add(lstAssignedRoles.Items[i]);
                lstAssignedRoles.Items.RemoveAt(i);
            }
        }
    }

    /// <summary>
    /// Add new and cancel event
    /// </summary>
    /// <param name="sender">The sending object Add New/Cancel Button</param>
    /// <param name="e">The Click Event Handler</param>
    protected void btnAdd_Click(object sender, EventArgs e)
    {
        this.ClearControls();
        // Adding Roles to listbox
        this.BindGroups();
        this.BindParentMenu();
    }

    #endregion

    #region Grid View Events

    /// <summary>
    /// Grid view event for deleting a row
    /// </summary>
    /// <param name="sender">The sending object</param>
    /// <param name="e">Delete event argument</param>
    protected void gvObjectList_RowDeleting(object sender, GridViewDeleteEventArgs e)
    {
        int objectID = Convert.ToInt32(gvObjectList.DataKeys[e.RowIndex].Value.ToString());
        if (CheckChildMenu(objectID))
        {
            ScriptManager.RegisterStartupScript(this, this.GetType(), "childmenupresent", "HideAddNew();alert('Cannot delete as there are associated child menu');", true);
        }
        else
        {
            SecurityObject objectDetail = new SecurityObject() { ObjectID = objectID };
            objectDetail.Delete();
            ScriptManager.RegisterStartupScript(this, this.GetType(), "hideaddnew", "HideAddNew();", true);

            // Delete associated user rights        
            this.BindObjects();
        }
    }

    /// <summary>
    /// Grid view row command event for editing
    /// </summary>
    /// <param name="sender">The sending object</param>
    /// <param name="e">Event arguments</param>
    protected void gvObjectList_RowCommand(object sender, GridViewCommandEventArgs e)
    {
        if (e.CommandName == "EditObject")
        {
            ScriptManager.RegisterStartupScript(this, this.GetType(), "showaddnew", "ShowAddNew();", true);
            GridViewRow row = (GridViewRow)(((LinkButton)e.CommandSource).NamingContainer);

            // Settting object details for Editing
            this.SetObjectDetails(int.Parse(this.gvObjectList.DataKeys[row.RowIndex].Value.ToString()));
        }
    }

    /// <summary>
    /// Set object details to the edit section
    /// </summary>
    /// <param name="objectDetailID">The Object ID</param>
    private void SetObjectDetails(int objectDetailID)
    {
        this.ClearControls();
        SecurityObject securityObject = new SecurityObject(objectDetailID);
        if (securityObject != null)
        {
            ObjectID = objectDetailID;

            // Adding Roles to listbox
            this.BindGroups();
            this.BindParentMenu();

            txtName.Text = securityObject.Name;
            txtDescription.Text = securityObject.Description;
            txtHref.Text = securityObject.Href;
            txtType.Text = securityObject.Type;
            txtTarget.Text = securityObject.Target;
            txtSortOrder.Text = securityObject.Sort.ToString();         
            ddlParentMenu.ClearSelection();
            if (securityObject.ParentObject != null)
            {
                if (ddlParentMenu.Items.FindByValue(securityObject.Parent.ToString()) != null)
                    ddlParentMenu.Items.FindByValue(securityObject.Parent.ToString()).Selected = true;
            }

            if (securityObject.Roles != null)
            {
                foreach (Group group in securityObject.Roles)
                {
                    lstAssignedRoles.Items.Add(new ListItem() { Text = group.Name, Value = group.GroupID.ToString() });
                    if (lstRoles.Items.FindByValue(group.GroupID.ToString()) != null)
                    {
                        lstRoles.Items.Remove(new ListItem() { Text = group.Name, Value = group.GroupID.ToString() });
                    }
                }
            }
        }
    }

    #endregion

    #region Private Functions

    private bool CheckChildMenu(int objectID)
    {
        DataTable dtObjects = this.GetObjects();
        int result = dtObjects.AsEnumerable()
                       .Where(r => r.Field<int>("Parent") == objectID)
                        .Count();
        return (result > 0);
    }

    /// <summary>
    /// Function to get the list
    /// of existing Objects.
    /// </summary>
    /// <returns>Datatable containing the list of Objects.</returns>
    private DataTable GetObjects()
    {
        SecurityObject objectDetails = new SecurityObject();
        return objectDetails.GetObjectList();
    }

    /// <summary>
    /// Function to bind list of Objects to 
    /// the grid view.
    /// </summary>
    private void BindObjects()
    {
        DataTable dtObjects = this.GetObjects();
        this.gvObjectList.DataSource = dtObjects;
        this.gvObjectList.DataBind();
    }

    /// <summary>
    /// Function to load menu items in 
    /// parent dropdownlist.
    /// </summary>
    /// <param name="dtObjects">The datatable containing the object details.</param>
    private void BindParentMenu()
    {
        DataTable dtObjects = this.GetObjects();
        var result = dtObjects.AsEnumerable()
                        .Where(r => r.Field<int>("ObjectID") != ObjectID)
                        .Select(row => new
                        {
                            Name = row.Field<string>("Name"),
                            ObjectID = row.Field<int>("ObjectID")
                        })
                        .Distinct();


        // Bind Dropdownlist        
        ddlParentMenu.Items.Clear();
        ddlParentMenu.DataSource = result;
        ddlParentMenu.DataTextField = "Name";
        ddlParentMenu.DataValueField = "ObjectID";
        ddlParentMenu.DataBind();

        // Adding default item
        ddlParentMenu.Items.Insert(0, new ListItem("[-- Select --]", "0"));
        if (ddlParentMenu.Items.Count > 0)
        {
            ddlParentMenu.ClearSelection();
            ddlParentMenu.SelectedIndex = 0;
        }
    }

    /// <summary>
    /// Function to get the list
    /// of existing Groups/groups.
    /// </summary>
    /// <returns>Datatable containing the list of Groups.</returns>
    private DataTable GetGroups()
    {
        CCollection groupCollectionList = new CCollection(new Group(), true);
        return groupCollectionList.DataTable;
    }

    /// <summary>
    /// Function to bind list of Groups to 
    /// the grid view.
    /// </summary>
    private void BindGroups()
    {
        this.lstRoles.DataSource = this.GetGroups();
        this.lstRoles.DataTextField = "Name";
        this.lstRoles.DataValueField = "GroupID";
        this.lstRoles.DataBind();
    }

    /// <summary>
    /// Function to clear the 
    /// controls value
    /// </summary>
    private void ClearControls()
    {
        txtSortOrder.Text = string.Empty;
        txtDescription.Text = string.Empty;
        txtName.Text = string.Empty;
        txtTarget.Text = string.Empty;
        txtType.Text = string.Empty;
        ddlParentMenu.ClearSelection();
        txtHref.Text = string.Empty;
        lblErrorAddNew.Text = string.Empty;
        ObjectID = 0;
        lstRoles.Items.Clear();
        lstAssignedRoles.Items.Clear();      
    }

    /// <summary>
    /// Function to check whether the object name
    /// is unique before add new/update operation.
    /// </summary>
    /// <param name="securityObject">The security object details.</param>
    /// <returns>Whether the save/update is successful</returns>
    private bool SaveObject(SecurityObject securityObject)
    {
        // Check whther the object name is unique
        DataTable dtGroupList = this.GetObjects();
        string selectExpression = string.Empty;
        if (securityObject.ObjectID == 0)
        {
            selectExpression = "Name = '" + securityObject.Name + "'";
        }
        else
        {
            selectExpression = "ObjectID <> '" + securityObject.ObjectID + "' AND Name = '" + securityObject.Name + "'";
        }

        DataRow[] modelDetails = dtGroupList.Select(selectExpression);
        if (modelDetails.Count() > 0)
        {
            txtName.Focus();
            return false;
        }
        else
        {
            securityObject.Save();
            securityObject.SaveMenuRoles();
            return true;
        }
    }

    #endregion
}